from threading import *
import sys
import socket
from time import time, ctime
import select
import re


conn_client={}

#host='localhost'
#port=0

nbCol=30
nbLignes=30

mySocketReception=None
mySocketEmission=None
thReception=None

console=False

class Client:

     def __init__(self,HOST,PORT,app):
          
          self.mySocketEmission=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#definition de la socket
          
          try:
               self.mySocketEmission.connect((HOST,PORT))#connection de la socket
               
          except socket.error:#si la connexion a echoue
               print "La liaison a echouee"
               sys.exit(-1)
               
          self.init=True
          self.app=app#liasion a l'application
          self.app.client=self
          self.Termine=False#parametre de terminaison

          self.reception=Thread(target=self.receive,name="Reception",args=())#declaration de la thread
          self.reception.start()

     def receive(self):#reception de donnees
          data="a"
          
          while data and not self.Termine:#tant qu'il y a des donnees et que ce n'est pas termine
               msgClient=self.mySocketEmission.recv(4000)
               traitementMsg(msgClient,self.app,self)#traitement du message
               
               if self.init:#si c'est le premier passage
                    self.mySocketEmission.send("listePartiesEnAttente")#besoin de recuperer la liste des parties en attente
                    self.init=False


def traitementMsg(msgClient,app,parent):#traitement du message

     if re.search("^nbPartiesEnAttente",msgClient)!=None:#si on recoit le nb de parties 
          if len(msgClient)>len("nbPartiesEnAttente\n"):#si on recoit un nombre apres
               msg,nbPartiesEnAttente,msgb,partiesEnAttente=msgClient.split("\n") #on separe les differentes variables avec \n
          else:#si l'envoi se fait separement, supression de \n a la fin des messages
               nbPartiesEnAttente=parent.mySocketEmission.recv(1024)[:-1]
               msgb=parent.mySocketEmission.recv(1024)[:-1]
               partiesEnAttente=parent.mySocketEmission.recv(1024)[:-1]
          if re.search(r"^[0-9]+$",nbPartiesEnAttente)!=None:#si nbPartiesEnAttente est bien 1 entier
               nbPartiesEnAttente=int(nbPartiesEnAttente)#transformation de la chaine de caracteres en un entier
               pb=False
               # si on a des parties en attente
               if nbPartiesEnAttente!=0:
                    if msgb=="ListePartiesEnAttente":
                         partiesEnAttente=partiesEnAttente.split(";")#on separe les parties en attentes
                         if len(partiesEnAttente)!=nbPartiesEnAttente:#si le nombre de parties envoyees est different de celui attendu
                              parent.mySocketEmission.send("Pb_NbPartie_ListePartie")#envoi d'un message d'erreur au serveur
                         else:#sinon
                              for i in range(nbPartiesEnAttente):#parcours de la liste des parties envoyees
                                        #print partiesEnAttente[i]
                                   partiesEnAttente[i]=partiesEnAttente[i].split(",")#les attributs d'une parties sont separes par ,
                                   if re.search(r"^[0-9]+$",partiesEnAttente[i][0])==None:#si le 2e attribut, correspondant au nb de joueurs attendus dans la partie n'est pas un entier
                                        parent.mySocketEmission.send("Pb_ListePartie_numPartie")#envoi d'un message d'erreur au serveur
                                        pb=True
                                        break
                                   partiesEnAttente[i][0]=int(partiesEnAttente[i][0])#si c'est bien un entier, la chaine de caracteres est transformee en entier

                                   
                                   if re.search(r"^[0-9]+$",partiesEnAttente[i][2])==None:#si le 2e attribut, correspondant au nb de joueurs attendus dans la partie n'est pas un entier
                                        print "Pb_ListePartie_nbJoueursAttendus"
                                        parent.mySocketEmission.send("Pb_ListePartie_nbJoueursAttendus")#envoi d'un message d'erreur au serveur
                                        pb=True
                                        break
                                   partiesEnAttente[i][2]=int(partiesEnAttente[i][2])#si c'est bien un entier, la chaine de caracteres est transformee en entier
                                   if re.search(r"^[0-9]+$",partiesEnAttente[i][4])==None:#si le 4e attribut, correspondant au nb de joueurs ayant deja rejoint la partie, n'est pas un entier
                                        print "Pb_ListePartie_nbJoueursDejaPresent"
                                        parent.mySocketEmission.send("Pb_ListePartie_nbJoueursDejaPresent") #envoie d'un message d'erreur au serveur
                                        pb=True
                                        break 
                                   partiesEnAttente[i][4]=int(partiesEnAttente[i][4])#sinon, transformation de la chaine de caracteres en 1 entier

               if not pb:#s'il n'y a aucun problemes dans le traitement des donnees
                    app.affichagePartieDisp(nbPartiesEnAttente,partiesEnAttente)#affichage des parties pour que le joueur en choisisse une                  
                         #fonction de gestion de l'affichage des parties en cours et des choix
                         #il faut ensuite conserver toutes les donnees de la partie choisie        
          else:#s'il le nb de parties envoyees est different de celui attendu
               parent.mySocketEmission.send("Pb_NbPartie")#envoi d'un message d'erreur au serveur
     elif re.search("^listeJoueursFinale",msgClient)!=None:#pour demarrer une partie, le serveur envoie aux joueurs la liste finale des joueurs
          if len(msgClient)>len("listeJoueursFinale\n"): #on separe les joueurs recus dans la liste
               msg,listeJoueurs=msgClient.split("\n")
               listeJoueurs=listeJoueurs.split(",")
          else:
               listeJoueurs=parent.mySocketEmission.recv(1024)[:-1].split(",")#les noms sont separes par des virgules
          app.debutPartie(listeJoueurs)#demarrage de la partie, avec la liste complete des joueurs
                    #fonction de gestion de la liste des joueurs
     elif re.search("^matrice",msgClient)!=None:#tous les joueurs, sauf celui qui a demarre la partie, recoivent la matrice contenant les positions des bombes
          if len(msgClient)>len("matrice\n"):#on recupere les donnees de la matrice
               msg,matrice=msgClient.split("\n")
               matrice=matrice.split(",")
          else:
               matrice=parent.mySocketEmission.recv(1024).split(",")[:-1]#les lignes sont separees par des ;
          pb=False
          for i in range(len(matrice)):#parcours des lignes
               if re.search("[0-9]+$",matrice[i])==None:#si le caractere ne correspond pas a un entier
                    parent.mySocketEmission.send("Pb_Matrice")#envoi d'un message d'erreur
                    pb=True
                    break
               else:
                    matrice[i]=int(matrice[i])#sinon, transformation 
          if not pb:#si 'il n'y a aucun pb sur la matrice
               app.Matrice(matrice)#enregistrement de la matrice et utilisation dans le demineur
                    #fonction de gestion et conservation de la matrice avec emplacement des bombes et des numeros
     elif re.search("^toi",msgClient)!=None:#si c'est au tour du joueur
          app.Tour()#le joueur joue

     elif re.search("^modificationCompteur",msgClient)!=None:#si le compteur d'un joueur est modifie
          if len(msgClient)>len("modificationCompteur\n"):
               msg,nomJoueurMod,valeurNewCompteur=msgClient.split("\n")#parametres de modifs
          else:
               nomJoueurMod=parent.mySocketEmission.recv(1024)[:-1]#recpetion du nom du joueur
               valeurNewCompteur=parent.mySocketEmission.recv(1024)[:-1]#reception de la nouvelle valeur

          if re.search(r"[0-9]+$",valeurNewCompteur)==None:#si elle ne correspond pas a un entier
               parent.mySocketEmission.send("Pb_modifCompteur")#envoi d'un message d'erreur

          else:#sinon
               valeurNewCompteur=int(valeurNewCompteur)#transformation de la chaine de caractere en un entier               app.modifCompteur(nomJoueurMod,valeurNewCompteur)#modification du compteur 
     
     elif re.search("^clic",msgClient)!=None:#le serveur envoi le clic d'un joueur
          if len(msgClient)>len("clic"):#on recupere les variables
               msg,click=msgClient.split("\n")
               click=click.split(",")
          else:
               click=parent.mySocketEmission.recv(1024)[:-1].split(",")#les coordonnees,le type de clic et le nom du joueur ayant clique sont separees par une virgule
                         
          if re.search(r"^[0-9]+$",click[0])==None or re.search(r"^[0-9]+$",click[1])==None:#si une des 2 coordonnees n'est pas 1 entier
               parent.mySocketEmission.send("Pb_click")#envoi d'un message d'erreur
          else:#sinon
               click[0]=int(click[0])#transformation des caracteres en entier
               click[1]=int(click[1])
               typ=click[2]#type de clic
               nom=click[3]#nom du joueur
               app.decouvrement(click,typ,nom)#decouvrement de la grille en fonction du type de clic, de ses coordonnees,...
                    #fonction de decouvrement de la grille

     elif re.search("^finPartie",msgClient)!=None:#si partie finie
          if len(msgClient)>len("finPartie\n"):#on recupere les variables de la fin de la partie( joueurs gagnants)
               msg,joueursGagnants=msgClient.split("\n")
               joueursGagnants=joueursGagnants.split(",")
          else:
               joueursGagnants=parent.mySocketEmission.recv(1024)[:-1].split(",")#noms des joueurs gagnants
          app.finPartie(joueursGagnants)#affichage de fin de partie et des gagnants
                    #fonction de gestion de la fin
               
     elif re.search("^aPerdu",msgClient)!=None:#si un joueur a perdu mais pas les autres
          if len(msgClient)>len("aPerdu\n"):
               msg,joueurPerdant=msgClient.split("\n")#qui a perdu
          else:
               joueurPerdant=parent.mySocketEmission.recv(1024)[:-1]
          app.aPerdu(joueurPerdant)#affichage que joueurPerdant a perdu et suppression du compteur

     elif re.search("^quitte",msgClient)!=None:#quand un joueur quitte la partie en cours
          if len(msgClient)>len("quitte\n"):
               msg,joueurQuittant=msgClient.split("\n")#qui quitte
          else:
               joueurQuittant=parent.mySocketEmission.recv(1024)[:-1]#nom du joueur qui quitte
          print "Quitte"+joueurQuittant
          app.quitte(joueurQuittant)
                   #affichage qu'il quitte et suppression du compteur



def debutClient(port,host,app):#fonction de lancement du client
     try:
          c=Client(host,port,app)#lancement de la classe client
     except:
          print "Erreur"
          sys.exit(-1)
     
